﻿using APP;
using AutoParameter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace APP
{
    public class FlowExecutor
    {
        private readonly FlowNode _rootNode;

        public FlowExecutor(FlowNode rootNode)
        {
            _rootNode = rootNode;
        }

        public async Task ExecuteAsync(FlowContext context)
        {
            await ExecuteNodeAsync(_rootNode, context);
        }

        private async Task ExecuteNodeAsync(FlowNode node, FlowContext context)
        {
            // 获取节点实例
            var nodeInstance = node.NodeInstance;
            var nodeType = node.NodeType;

            // 获取输入和输出类型
            var inputType = nodeType.GetInterfaces()
                .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IFlowNode<,>))
                ?.GetGenericArguments()[0];
            var outputType = nodeType.GetInterfaces()
                .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IFlowNode<,>))
                ?.GetGenericArguments()[1];

            // 创建输入和输出对象
            var input = Activator.CreateInstance(inputType);
            var output = Activator.CreateInstance(outputType);

            // 自动赋值输入
            // 自动赋值输入
            var mapInput = PropertyMapper.CreateMap(context.GlobalInput.GetType(), inputType);
            mapInput(context.GlobalInput, input);

            // 执行节点逻辑
            var executeMethod = nodeType.GetMethod("ExecuteAsync");
            var task = (Task)executeMethod.Invoke(nodeInstance, new[] { input });
            await task;

            var resultProperty = task.GetType().GetProperty("Result");
            var result = resultProperty.GetValue(task);

            // 自动赋值输出
            var mapOutputMethod = typeof(PropertyMapper).GetMethod(nameof(PropertyMapper.CreateMap))
                .MakeGenericMethod(outputType, context.GlobalOutput.GetType());
            var mapOutput = (Action<object, object>)mapOutputMethod.Invoke(null, null);
            mapOutput(result, context.GlobalOutput);

            // 执行子节点
            var childTasks = node.Children.Select(child => ExecuteNodeAsync(child, context));
            await Task.WhenAll(childTasks);
        }
    }
}
